Introduction
Scientific question: What is the most differentially expressed gene associated with Crohn’s disease from a 55,000 gene data set – including samples of Crohn’s patients and normal patients – and is it conserved across the close phylogenetic relatives of homo sapiens, to include chimpanzees and gorillas?
Crohn’s disease is a type of inflammatory bowel disease. Genes commonly associated with inflammation caused by IBD and CD are called interleukins, which are a type of cytokines. There are over 50 interleukins found in the human genome, some of which are inflammatory cytokines (Brocker et al., 2010). The most commonly identified IL genes in patients with Crohn’s Disease are IL-10, IL-17, and IL-23. IL-23 activates Th17 cells, which in turn increases production of IL-17 (Zhu et al., 2018). The mRNA expression of IL-17 has been detected in CD3+ lymphocyte cells, CD4+ T cells, and CD68+ macrophage cells (Fujino et al., 2003). IL-23 has also been found to upregulate the expression of IL-10 (Vanden Eijnden et al., 2005). Each of these pathways leads to an increase in inflammation due to the increased expression of the inflammatory cytokines. Evidence suggests mammals including chimpanzees have interleukin genes that are commonly associated with inflammation (Burger et al., 1994), however, further analyses have not been done to identify if the most differentially expressed genes related to Crohn’s in humans are also found in close phlogenetic relatives. Although interleukin genes are commonly associated with the inflammation involved in Crohn’s, there may be other genes and pathways associated. By analyzing this data set, I will determine other potential genes that are associated with Crohn’s.
Scientific hypothesis: If I analyze the gene expression analysis from 55,000 genes across 30 samples of Crohn’s patients and 30 samples without Crohn’s, then I can identify the most differentially expressed and upregulated gene associated with Crohn’s and confirm the gene is conserved across close phylogenetic relatives of homo sapiens.
I have downloaded a data set from NCBI GEO containing the gene expression levels of 55,000 genes with samples from Crohn’s patients, ulceritive colitis patients, and normal; I will only be analyzing the samples of Crohn’s and the control group. I will run RNASeq (DESeq) to identify the most differentially expressed genes in Crohn’s vs the control group. In order to present this data, I will subset the top 10 positive and negative log2foldchange values, and use a heatmap to show gene expression levels of these 20 genes, which will be explained more below. I will also visualize the results using a volcano plot to show the log2foldchange values vs the -log(p-values) of the DESeq results. After obtaining the nucleotide sequence of the most differentially expressed and upregulated gene in Crohn’s samples, I will run this fasta file through BLAST search to identify if the gene is conserved across close phylogenetic relatives of homo sapiens.
The data set used in this analysis includes over 55,000 genes; in order to narrow it down, I have used na.omit() to remove any lines in the data set that are either missing gene names or missing values. Because analyzing 170 total samples may be too much data for DESeq, I will be analyzing 30 samples from Crohn’s patients and 30 samples from control patients.
Package Descriptions Below are the packages necessary for running this code. 1. pheatmap: “Pretty heat map” - This package is going to be used to create a visual heatmap for interpreting the gene expression data pulled from DESeq. This code will allow us to have more control over the dimensions and appearance of the heatmap. 2. RColorBrewer: This package is used for specifying the colors of the pheatmap and is completely optional and up to the individual on what colors they want for the heatmap. This package includes specific color combinations. 3. DESeq2: This package is used to run differential expression analysis on count data from a given data set (RNASeq). This code will output log2foldchange values and p-values of a given gene expression data set, which will later be used for the heatmap. 4. Biostrings: “Manipulation of biological strings” - This package will be used to convert a fasta file to DNA string set. 5. Annotate: This package will be used to run blastSequences() on the loaded fasta file as a DNA string set to identify any similar sequences from other species. 6. seqinr: This package is used for retrieving and analyzing biological sequences, and will specifically be used to read in a FASTA file. 7. apeglm: A package for shrinkage estimators in GLM coefficients - used for the lfcshrink() function after running DESeq.
These packages will need to be loaded, as they are already installed in my R studio.
library(pheatmap)
library(RColorBrewer)
library(DESeq2)
Loading required package: S4Vectors
Loading required package: stats4
Loading required package: BiocGenerics
Attaching package: ‘BiocGenerics’
The following objects are masked from ‘package:stats’:
IQR, mad, sd, var, xtabs
The following objects are masked from ‘package:base’:
anyDuplicated, append, as.data.frame, basename, cbind,
colnames, dirname, do.call, duplicated, eval, evalq,
Filter, Find, get, grep, grepl, intersect, is.unsorted,
lapply, Map, mapply, match, mget, order, paste, pmax,
pmax.int, pmin, pmin.int, Position, rank, rbind, Reduce,
rownames, sapply, setdiff, sort, table, tapply, union,
unique, unsplit, which.max, which.min
Attaching package: ‘S4Vectors’
The following objects are masked from ‘package:base’:
expand.grid, I, unname
Loading required package: IRanges
Attaching package: ‘IRanges’
The following object is masked from ‘package:grDevices’:
windows
Loading required package: GenomicRanges
Loading required package: GenomeInfoDb
Loading required package: SummarizedExperiment
Loading required package: MatrixGenerics
Loading required package: matrixStats
Attaching package: ‘MatrixGenerics’
The following objects are masked from ‘package:matrixStats’:
colAlls, colAnyNAs, colAnys, colAvgsPerRowSet,
colCollapse, colCounts, colCummaxs, colCummins,
colCumprods, colCumsums, colDiffs, colIQRDiffs, colIQRs,
colLogSumExps, colMadDiffs, colMads, colMaxs, colMeans2,
colMedians, colMins, colOrderStats, colProds,
colQuantiles, colRanges, colRanks, colSdDiffs, colSds,
colSums2, colTabulates, colVarDiffs, colVars,
colWeightedMads, colWeightedMeans, colWeightedMedians,
colWeightedSds, colWeightedVars, rowAlls, rowAnyNAs,
rowAnys, rowAvgsPerColSet, rowCollapse, rowCounts,
rowCummaxs, rowCummins, rowCumprods, rowCumsums,
rowDiffs, rowIQRDiffs, rowIQRs, rowLogSumExps,
rowMadDiffs, rowMads, rowMaxs, rowMeans2, rowMedians,
rowMins, rowOrderStats, rowProds, rowQuantiles,
rowRanges, rowRanks, rowSdDiffs, rowSds, rowSums2,
rowTabulates, rowVarDiffs, rowVars, rowWeightedMads,
rowWeightedMeans, rowWeightedMedians, rowWeightedSds,
rowWeightedVars
Loading required package: Biobase
Welcome to Bioconductor
Vignettes contain introductory material; view with
'browseVignettes()'. To cite Bioconductor, see
'citation("Biobase")', and for packages
'citation("pkgname")'.
Attaching package: ‘Biobase’
The following object is masked from ‘package:MatrixGenerics’:
rowMedians
The following objects are masked from ‘package:matrixStats’:
anyMissing, rowMedians
library(Biostrings)
Loading required package: XVector
Attaching package: ‘Biostrings’
The following object is masked from ‘package:base’:
strsplit
library(annotate)
Loading required package: AnnotationDbi
Loading required package: XML
library(seqinr)
Attaching package: ‘seqinr’
The following object is masked from ‘package:Biostrings’:
translate
The following object is masked from ‘package:matrixStats’:
count
The following package needed to be installed in order to use the apeglm paramemeter for lfcShrink after running DESeq.
# #if (!require("BiocManager", quietly = TRUE))
# install.packages("BiocManager")
#
# BiocManager::install("apeglm")
library(apeglm)
Performing Bioinformatics Analysis
Below is the code needed to read in the gene expression normalized counts as a .tsv file.
# gene_data is a list variable and a global variable
gene_data <- read.table(file = "GSE165512_normalized_counts.tsv.gz", sep = "\t", header = TRUE)
# typeof(gene_data)
print(gene_data)
NA
I will now be omitting any empty values in the data frame with na.omit, then assigning vectors for DESeq.
# Create count data: leave out gene ID column first
# this is a list variable and global variable
gene_norm <- gene_data[,-2]
# removing any rows with "NA" as gene names or values
gene_norm2 <- na.omit(gene_norm)
# typeof(gene_norm2)
# Save gene expression data as matrix (numerical), this is a global variable
gene_count <- as.matrix(gene_norm2[1:52219, c(111:140, 2:31)])
# print(gene_count)
# Create metadata for colData value. list variable and global variable
condition <- c(rep(c("control"), times = 30), rep(c("crohns"), times = 30))
genotype <- gene_norm[1:60,]
gene_meta <- data.frame(genotype, condition)
# typeof(gene_meta)
Now the number of genes is down to 52,219.
Now we will run DESeq. The function DESeqDataSetFromMatrix will run differential expression analysis on the normalized gene counts. The design is based on the condition, Crohn’s vs control.
dds_gene$condition <- relevel(dds_gene$condition, ref="control")
res <- results(dds_gene)
rownames(dds_gene) <- gene_norm[1:52219,1]
summary(res)
out of 47733 with nonzero total read count
adjusted p-value < 0.1
LFC > 0 (up) : 2453, 5.1%
LFC < 0 (down) : 5702, 12%
outliers [1] : 0, 0%
low counts [2] : 19221, 40%
(mean count < 1)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results
Based on the summary of results, 2453 genes are upregulated in Crohn’s and 5702 are downregulated.
The most differentially expressed gene that is downregulated in Crohn’s is RP11-2K6.2, while the most differentially expressed gene that is upregulated is PRAC1.
Plotting the results
First, we have to transform normalized counts before we can plot the heatmap.

The heatmap shows the top 10 differentially expressed genes in Crohn’s vs the control that are downregulated, and the top 10 differentially expressed genes that are upregulated. The log2 Fold Change is a log-ratio of the gene expression values in two conditions: Crohn’s and control. A negative lfc value represents a gene that is downregulated in Crohn’s vs the control, while a positive lfc value represents a gene that is upregulated in Crohn’s vs the control. The legend on the right signifies log2foldchange values by color, on a scale of -2 to 6.
I will plot the results of DESeq as a volcano plot which is used to visualize the log2(foldchange) values vs the -log(p-values).
# Plot results of DESeq to visualize data as a volcano plot. the plot() function is built into the base package of R.
plot(res$log2FoldChange, -log(res$padj),
xlab="Log2(FoldChange)",
ylab="-Log(P-value)")
abline(v=c(-2,2), col="darkgray", lty=2)

#plot dispersion estimates
plotDispEsts(dds_gene)

The volcano plot shows the general trend of the data, with a group of genes around the -25 lfc value while the rest are grouped between -10 and 5. The dispersion plot shows the variance in gene expression for the DESeq data, with the red line signifying the fitted line for the data shown. Based on the graphs, there do not appear to be any outliers and the data appears consistent.
I have downloaded a FASTA file from NCBI for the gene PRAC1, which is the most differentially expressed and upregulated gene in Crohn’s. I will run BLAST on this sequence to determine the top 10 hits.
# run BLAST on s4 variable
blastSequences(DNA_PRAC1, "nr", hitListSize="10", filter="L", expect="10", program="blastn", as=c("data.frame"))
estimated response time 25 seconds
The most differentially expressed gene found in the data set containing Crohn’s samples of homo sapiens is PRAC1, which is a small nuclear protein. The PRAC1 gene has been found to be more expressed in tissues such as the prostate and colon, and has been linked to prostate cancer (Kim et al., 2015). This gene is found in close phylogenetic relatives of homo sapiens, but a lack of evidence exists to show if these species express the PRAC1 gene.
The BLAST search runs the PRAC1 nucleotide sequence through NCBI BLAST, and returns the top 10 matches here. There are 5 matches to close phylogenetic relatives of homo sapiens: Bonobo (Pan paniscus), Chimpanzee (Pan troglodytes), Gorilla (Gorilla gorilla), Orangutan (Pongo abelii), and Gibbon (Nomascus leucogenys). Each of these appears as “predicted,” which means that although the nucleotide sequence of the PRAC1 gene is similar to these species, there is no experimental evidence showing that this gene is transcribed to produce a protein. The sequence match is as high as 98.85% for the Bonobo and as low as 86.10% for the Gibbon, however there is no evidence showing that the genomes’ of these five species express this gene.
LS0tDQp0aXRsZTogIklkZW50aWZ5aW5nIERpZmZlcmVudGlhbGx5IEV4cHJlc3NlZCBHZW5lcyBpbiBDcm9obidzIERpc2Vhc2UiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpJbnRyb2R1Y3Rpb24NCg0KU2NpZW50aWZpYyBxdWVzdGlvbjogV2hhdCBpcyB0aGUgbW9zdCBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZSBhc3NvY2lhdGVkIHdpdGggQ3JvaG7igJlzIGRpc2Vhc2UgZnJvbSBhIDU1LDAwMCBnZW5lIGRhdGEgc2V0IC0tIGluY2x1ZGluZyBzYW1wbGVzIG9mIENyb2huJ3MgcGF0aWVudHMgYW5kIG5vcm1hbCBwYXRpZW50cyAtLSBhbmQgaXMgaXQgY29uc2VydmVkIGFjcm9zcyB0aGUgY2xvc2UgcGh5bG9nZW5ldGljIHJlbGF0aXZlcyBvZiBob21vIHNhcGllbnMsIHRvIGluY2x1ZGUgY2hpbXBhbnplZXMgYW5kIGdvcmlsbGFzPw0KDQpDcm9obidzIGRpc2Vhc2UgaXMgYSB0eXBlIG9mIGluZmxhbW1hdG9yeSBib3dlbCBkaXNlYXNlLiBHZW5lcyBjb21tb25seSBhc3NvY2lhdGVkIHdpdGggaW5mbGFtbWF0aW9uIGNhdXNlZCBieSBJQkQgYW5kIENEIGFyZSBjYWxsZWQgaW50ZXJsZXVraW5zLCB3aGljaCBhcmUgYSB0eXBlIG9mIGN5dG9raW5lcy4gVGhlcmUgYXJlIG92ZXIgNTAgaW50ZXJsZXVraW5zIGZvdW5kIGluIHRoZSBodW1hbiBnZW5vbWUsIHNvbWUgb2Ygd2hpY2ggYXJlIGluZmxhbW1hdG9yeSBjeXRva2luZXMgKEJyb2NrZXIgZXQgYWwuLCAyMDEwKS4gDQpUaGUgbW9zdCBjb21tb25seSBpZGVudGlmaWVkIElMIGdlbmVzIGluIHBhdGllbnRzIHdpdGggQ3JvaG4ncyBEaXNlYXNlIGFyZSBJTC0xMCwgSUwtMTcsIGFuZCBJTC0yMy4gSUwtMjMgYWN0aXZhdGVzIFRoMTcgY2VsbHMsIHdoaWNoIGluIHR1cm4gaW5jcmVhc2VzIHByb2R1Y3Rpb24gb2YgSUwtMTcgKFpodSBldCBhbC4sIDIwMTgpLiBUaGUgbVJOQSBleHByZXNzaW9uIG9mIElMLTE3IGhhcyBiZWVuIGRldGVjdGVkIGluIENEMysgbHltcGhvY3l0ZSBjZWxscywgQ0Q0KyBUIGNlbGxzLCBhbmQgQ0Q2OCsgbWFjcm9waGFnZSBjZWxscyAoRnVqaW5vIGV0IGFsLiwgMjAwMykuIElMLTIzIGhhcyBhbHNvIGJlZW4gZm91bmQgdG8gdXByZWd1bGF0ZSB0aGUgZXhwcmVzc2lvbiBvZiBJTC0xMCAoVmFuZGVuIEVpam5kZW4gZXQgYWwuLCAyMDA1KS4gRWFjaCBvZiB0aGVzZSBwYXRod2F5cyBsZWFkcyB0byBhbiBpbmNyZWFzZSBpbiBpbmZsYW1tYXRpb24gZHVlIHRvIHRoZSBpbmNyZWFzZWQgZXhwcmVzc2lvbiBvZiB0aGUgaW5mbGFtbWF0b3J5IGN5dG9raW5lcy4gRXZpZGVuY2Ugc3VnZ2VzdHMgbWFtbWFscyBpbmNsdWRpbmcgY2hpbXBhbnplZXMgaGF2ZSBpbnRlcmxldWtpbiBnZW5lcyB0aGF0IGFyZSBjb21tb25seSBhc3NvY2lhdGVkIHdpdGggaW5mbGFtbWF0aW9uIChCdXJnZXIgZXQgYWwuLCAxOTk0KSwgaG93ZXZlciwgZnVydGhlciBhbmFseXNlcyBoYXZlIG5vdCBiZWVuIGRvbmUgdG8gaWRlbnRpZnkgaWYgdGhlIG1vc3QgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIHJlbGF0ZWQgdG8gQ3JvaG4ncyBpbiBodW1hbnMgYXJlIGFsc28gZm91bmQgaW4gY2xvc2UgcGhsb2dlbmV0aWMgcmVsYXRpdmVzLiANCkFsdGhvdWdoIGludGVybGV1a2luIGdlbmVzIGFyZSBjb21tb25seSBhc3NvY2lhdGVkIHdpdGggdGhlIGluZmxhbW1hdGlvbiBpbnZvbHZlZCBpbiBDcm9obidzLCB0aGVyZSBtYXkgYmUgb3RoZXIgZ2VuZXMgYW5kIHBhdGh3YXlzIGFzc29jaWF0ZWQuIEJ5IGFuYWx5emluZyB0aGlzIGRhdGEgc2V0LCBJIHdpbGwgZGV0ZXJtaW5lIG90aGVyIHBvdGVudGlhbCBnZW5lcyB0aGF0IGFyZSBhc3NvY2lhdGVkIHdpdGggQ3JvaG4ncy4NCg0KU2NpZW50aWZpYyBoeXBvdGhlc2lzOiBJZiBJIGFuYWx5emUgdGhlIGdlbmUgZXhwcmVzc2lvbiBhbmFseXNpcyBmcm9tIDU1LDAwMCBnZW5lcyBhY3Jvc3MgMzAgc2FtcGxlcyBvZiBDcm9obidzIHBhdGllbnRzIGFuZCAzMCBzYW1wbGVzIHdpdGhvdXQgQ3JvaG4ncywgdGhlbiBJIGNhbiBpZGVudGlmeSB0aGUgbW9zdCBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYW5kIHVwcmVndWxhdGVkIGdlbmUgYXNzb2NpYXRlZCB3aXRoIENyb2huJ3MgYW5kIGNvbmZpcm0gdGhlIGdlbmUgaXMgY29uc2VydmVkIGFjcm9zcyBjbG9zZSBwaHlsb2dlbmV0aWMgcmVsYXRpdmVzIG9mIGhvbW8gc2FwaWVucy4NCg0KSSBoYXZlIGRvd25sb2FkZWQgYSBkYXRhIHNldCBmcm9tIE5DQkkgR0VPIGNvbnRhaW5pbmcgdGhlIGdlbmUgZXhwcmVzc2lvbiBsZXZlbHMgb2YgNTUsMDAwIGdlbmVzIHdpdGggc2FtcGxlcyBmcm9tIENyb2huJ3MgcGF0aWVudHMsIHVsY2VyaXRpdmUgY29saXRpcyBwYXRpZW50cywgYW5kIG5vcm1hbDsgSSB3aWxsIG9ubHkgYmUgYW5hbHl6aW5nIHRoZSBzYW1wbGVzIG9mIENyb2huJ3MgYW5kIHRoZSBjb250cm9sIGdyb3VwLiBJIHdpbGwgcnVuIFJOQVNlcSAoREVTZXEpIHRvIGlkZW50aWZ5IHRoZSBtb3N0IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBpbiBDcm9obidzIHZzIHRoZSBjb250cm9sIGdyb3VwLiBJbiBvcmRlciB0byBwcmVzZW50IHRoaXMgZGF0YSwgSSB3aWxsIHN1YnNldCB0aGUgdG9wIDEwIHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSBsb2cyZm9sZGNoYW5nZSB2YWx1ZXMsIGFuZCB1c2UgYSBoZWF0bWFwIHRvIHNob3cgZ2VuZSBleHByZXNzaW9uIGxldmVscyBvZiB0aGVzZSAyMCBnZW5lcywgd2hpY2ggd2lsbCBiZSBleHBsYWluZWQgbW9yZSBiZWxvdy4gSSB3aWxsIGFsc28gdmlzdWFsaXplIHRoZSByZXN1bHRzIHVzaW5nIGEgdm9sY2FubyBwbG90IHRvIHNob3cgdGhlIGxvZzJmb2xkY2hhbmdlIHZhbHVlcyB2cyB0aGUgLWxvZyhwLXZhbHVlcykgb2YgdGhlIERFU2VxIHJlc3VsdHMuIEFmdGVyIG9idGFpbmluZyB0aGUgbnVjbGVvdGlkZSBzZXF1ZW5jZSBvZiB0aGUgbW9zdCBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYW5kIHVwcmVndWxhdGVkIGdlbmUgaW4gQ3JvaG4ncyBzYW1wbGVzLCBJIHdpbGwgcnVuIHRoaXMgZmFzdGEgZmlsZSB0aHJvdWdoIEJMQVNUIHNlYXJjaCB0byBpZGVudGlmeSBpZiB0aGUgZ2VuZSBpcyBjb25zZXJ2ZWQgYWNyb3NzIGNsb3NlIHBoeWxvZ2VuZXRpYyByZWxhdGl2ZXMgb2YgaG9tbyBzYXBpZW5zLiANCg0KVGhlIGRhdGEgc2V0IHVzZWQgaW4gdGhpcyBhbmFseXNpcyBpbmNsdWRlcyBvdmVyIDU1LDAwMCBnZW5lczsgaW4gb3JkZXIgdG8gbmFycm93IGl0IGRvd24sIEkgaGF2ZSB1c2VkIG5hLm9taXQoKSB0byByZW1vdmUgYW55IGxpbmVzIGluIHRoZSBkYXRhIHNldCB0aGF0IGFyZSBlaXRoZXIgbWlzc2luZyBnZW5lIG5hbWVzIG9yIG1pc3NpbmcgdmFsdWVzLiBCZWNhdXNlIGFuYWx5emluZyAxNzAgdG90YWwgc2FtcGxlcyBtYXkgYmUgdG9vIG11Y2ggZGF0YSBmb3IgREVTZXEsIEkgd2lsbCBiZSBhbmFseXppbmcgMzAgc2FtcGxlcyBmcm9tIENyb2huJ3MgcGF0aWVudHMgYW5kIDMwIHNhbXBsZXMgZnJvbSBjb250cm9sIHBhdGllbnRzLg0KDQpQYWNrYWdlIERlc2NyaXB0aW9ucw0KQmVsb3cgYXJlIHRoZSBwYWNrYWdlcyBuZWNlc3NhcnkgZm9yIHJ1bm5pbmcgdGhpcyBjb2RlLg0KMS4gcGhlYXRtYXA6ICJQcmV0dHkgaGVhdCBtYXAiIC0gVGhpcyBwYWNrYWdlIGlzIGdvaW5nIHRvIGJlIHVzZWQgdG8gY3JlYXRlIGEgdmlzdWFsIGhlYXRtYXAgZm9yIGludGVycHJldGluZyB0aGUgZ2VuZSBleHByZXNzaW9uIGRhdGEgcHVsbGVkIGZyb20gREVTZXEuIFRoaXMgY29kZSB3aWxsIGFsbG93IHVzIHRvIGhhdmUgbW9yZSBjb250cm9sIG92ZXIgdGhlIGRpbWVuc2lvbnMgYW5kIGFwcGVhcmFuY2Ugb2YgdGhlIGhlYXRtYXAuDQoyLiBSQ29sb3JCcmV3ZXI6IFRoaXMgcGFja2FnZSBpcyB1c2VkIGZvciBzcGVjaWZ5aW5nIHRoZSBjb2xvcnMgb2YgdGhlIHBoZWF0bWFwIGFuZCBpcyBjb21wbGV0ZWx5IG9wdGlvbmFsIGFuZCB1cCB0byB0aGUgaW5kaXZpZHVhbCBvbiB3aGF0IGNvbG9ycyB0aGV5IHdhbnQgZm9yIHRoZSBoZWF0bWFwLiBUaGlzIHBhY2thZ2UgaW5jbHVkZXMgc3BlY2lmaWMgY29sb3IgY29tYmluYXRpb25zLg0KMy4gREVTZXEyOiBUaGlzIHBhY2thZ2UgaXMgdXNlZCB0byBydW4gZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMgb24gY291bnQgZGF0YSBmcm9tIGEgZ2l2ZW4gZGF0YSBzZXQgKFJOQVNlcSkuIFRoaXMgY29kZSB3aWxsIG91dHB1dCBsb2cyZm9sZGNoYW5nZSB2YWx1ZXMgYW5kIHAtdmFsdWVzIG9mIGEgZ2l2ZW4gZ2VuZSBleHByZXNzaW9uIGRhdGEgc2V0LCB3aGljaCB3aWxsIGxhdGVyIGJlIHVzZWQgZm9yIHRoZSBoZWF0bWFwLg0KNC4gQmlvc3RyaW5nczogIk1hbmlwdWxhdGlvbiBvZiBiaW9sb2dpY2FsIHN0cmluZ3MiIC0gVGhpcyBwYWNrYWdlIHdpbGwgYmUgdXNlZCB0byBjb252ZXJ0IGEgZmFzdGEgZmlsZSB0byBETkEgc3RyaW5nIHNldC4NCjUuIEFubm90YXRlOiBUaGlzIHBhY2thZ2Ugd2lsbCBiZSB1c2VkIHRvIHJ1biBibGFzdFNlcXVlbmNlcygpIG9uIHRoZSBsb2FkZWQgZmFzdGEgZmlsZSBhcyBhIEROQSBzdHJpbmcgc2V0IHRvIGlkZW50aWZ5IGFueSBzaW1pbGFyIHNlcXVlbmNlcyBmcm9tIG90aGVyIHNwZWNpZXMuDQo2LiBzZXFpbnI6IFRoaXMgcGFja2FnZSBpcyB1c2VkIGZvciByZXRyaWV2aW5nIGFuZCBhbmFseXppbmcgYmlvbG9naWNhbCBzZXF1ZW5jZXMsIGFuZCB3aWxsIHNwZWNpZmljYWxseSBiZSB1c2VkIHRvIHJlYWQgaW4gYSBGQVNUQSBmaWxlLg0KNy4gYXBlZ2xtOiBBIHBhY2thZ2UgZm9yIHNocmlua2FnZSBlc3RpbWF0b3JzIGluIEdMTSBjb2VmZmljaWVudHMgLSB1c2VkIGZvciB0aGUgbGZjc2hyaW5rKCkgZnVuY3Rpb24gYWZ0ZXIgcnVubmluZyBERVNlcS4NCg0KVGhlc2UgcGFja2FnZXMgd2lsbCBuZWVkIHRvIGJlIGxvYWRlZCwgYXMgdGhleSBhcmUgYWxyZWFkeSBpbnN0YWxsZWQgaW4gbXkgUiBzdHVkaW8uDQoNCmBgYHtyfQ0KbGlicmFyeShwaGVhdG1hcCkNCmxpYnJhcnkoUkNvbG9yQnJld2VyKQ0KbGlicmFyeShERVNlcTIpDQpsaWJyYXJ5KEJpb3N0cmluZ3MpDQpsaWJyYXJ5KGFubm90YXRlKQ0KbGlicmFyeShzZXFpbnIpDQpgYGANCg0KVGhlIGZvbGxvd2luZyBwYWNrYWdlIG5lZWRlZCB0byBiZSBpbnN0YWxsZWQgaW4gb3JkZXIgdG8gdXNlIHRoZSBhcGVnbG0gcGFyYW1lbWV0ZXIgZm9yIGxmY1NocmluayBhZnRlciBydW5uaW5nIERFU2VxLg0KDQpgYGB7cn0NCiMgI2lmICghcmVxdWlyZSgiQmlvY01hbmFnZXIiLCBxdWlldGx5ID0gVFJVRSkpDQojICAgICBpbnN0YWxsLnBhY2thZ2VzKCJCaW9jTWFuYWdlciIpDQojIA0KIyBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiYXBlZ2xtIikNCmxpYnJhcnkoYXBlZ2xtKQ0KYGBgDQoNClBlcmZvcm1pbmcgQmlvaW5mb3JtYXRpY3MgQW5hbHlzaXMNCg0KQmVsb3cgaXMgdGhlIGNvZGUgbmVlZGVkIHRvIHJlYWQgaW4gdGhlIGdlbmUgZXhwcmVzc2lvbiBub3JtYWxpemVkIGNvdW50cyBhcyBhIC50c3YgZmlsZS4NCmBgYHtyfQ0KIyBnZW5lX2RhdGEgaXMgYSBsaXN0IHZhcmlhYmxlIGFuZCBhIGdsb2JhbCB2YXJpYWJsZQ0KZ2VuZV9kYXRhIDwtIHJlYWQudGFibGUoZmlsZSA9ICJHU0UxNjU1MTJfbm9ybWFsaXplZF9jb3VudHMudHN2Lmd6Iiwgc2VwID0gIlx0IiwgaGVhZGVyID0gVFJVRSkNCiMgdHlwZW9mKGdlbmVfZGF0YSkNCiMgcHJpbnQoZ2VuZV9kYXRhKQ0KDQpgYGANCg0KSSB3aWxsIG5vdyBiZSBvbWl0dGluZyBhbnkgZW1wdHkgdmFsdWVzIGluIHRoZSBkYXRhIGZyYW1lIHdpdGggbmEub21pdCwgdGhlbiBhc3NpZ25pbmcgdmVjdG9ycyBmb3IgREVTZXEuDQoNCmBgYHtyfQ0KIyBDcmVhdGUgY291bnQgZGF0YTogbGVhdmUgb3V0IGdlbmUgSUQgY29sdW1uIGZpcnN0DQojIHRoaXMgaXMgYSBsaXN0IHZhcmlhYmxlIGFuZCBnbG9iYWwgdmFyaWFibGUNCmdlbmVfbm9ybSA8LSBnZW5lX2RhdGFbLC0yXQ0KIyByZW1vdmluZyBhbnkgcm93cyB3aXRoICJOQSIgYXMgZ2VuZSBuYW1lcyBvciB2YWx1ZXMNCmdlbmVfbm9ybSA8LSBuYS5vbWl0KGdlbmVfbm9ybSkNCiMgdHlwZW9mKGdlbmVfbm9ybSkNCg0KIyBTYXZlIGdlbmUgZXhwcmVzc2lvbiBkYXRhIGFzIG1hdHJpeCAobnVtZXJpY2FsKSwgdGhpcyBpcyBhIGdsb2JhbCB2YXJpYWJsZQ0KZ2VuZV9jb3VudCA8LSBhcy5tYXRyaXgoZ2VuZV9ub3JtWzE6NTIyMTksIGMoMTExOjE0MCwgMjozMSldKQ0KIyBwcmludChnZW5lX2NvdW50KQ0KDQojIENyZWF0ZSBtZXRhZGF0YSBmb3IgY29sRGF0YSB2YWx1ZS4gbGlzdCB2YXJpYWJsZSBhbmQgZ2xvYmFsIHZhcmlhYmxlDQpjb25kaXRpb24gPC0gYyhyZXAoYygiY29udHJvbCIpLCB0aW1lcyA9IDMwKSwgcmVwKGMoImNyb2hucyIpLCB0aW1lcyA9IDMwKSkNCmdlbm90eXBlIDwtIGdlbmVfbm9ybVsxOjYwLF0NCmdlbmVfbWV0YSA8LSBkYXRhLmZyYW1lKGdlbm90eXBlLCBjb25kaXRpb24pDQojIHR5cGVvZihnZW5lX21ldGEpDQoNCmBgYA0KTm93IHRoZSBudW1iZXIgb2YgZ2VuZXMgaXMgZG93biB0byA1MiwyMTkuDQoNCk5vdyB3ZSB3aWxsIHJ1biBERVNlcS4gVGhlIGZ1bmN0aW9uIERFU2VxRGF0YVNldEZyb21NYXRyaXggd2lsbCBydW4gZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMgb24gdGhlIG5vcm1hbGl6ZWQgZ2VuZSBjb3VudHMuIFRoZSBkZXNpZ24gaXMgYmFzZWQgb24gdGhlIGNvbmRpdGlvbiwgQ3JvaG4ncyB2cyBjb250cm9sLg0KDQpgYGB7cn0NCiMgUnVuIERFU2VxIHVzaW5nIGdlbmVfY291bnQgYW5kIGdlbmVfbWV0YSBnbG9iYWwgdmFyaWFibGVzDQpkZHNfZ2VuZSA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IHJvdW5kKGdlbmVfY291bnQpLCBjb2xEYXRhID0gZ2VuZV9tZXRhLCBkZXNpZ24gPSB+IGNvbmRpdGlvbikNCiMgZGRzX2dlbmUgaXMgYW4gUzQgdmFyaWFibGUgYW5kIGdsb2JhbA0KZGRzX2dlbmUgPC0gREVTZXEoZGRzX2dlbmUpDQojIHNldHRpbmcgcmVmZXJlbmNlIGxldmVsIGFzIHRoZSBjb250cm9sDQpkZHNfZ2VuZSRjb25kaXRpb24gPC0gcmVsZXZlbChkZHNfZ2VuZSRjb25kaXRpb24sIHJlZj0iY29udHJvbCIpDQpyZXMgPC0gcmVzdWx0cyhkZHNfZ2VuZSkNCnJvd25hbWVzKGRkc19nZW5lKSA8LSBnZW5lX25vcm1bMTo1MjIxOSwxXQ0Kc3VtbWFyeShyZXMpDQoNCmBgYA0KDQpCYXNlZCBvbiB0aGUgc3VtbWFyeSBvZiByZXN1bHRzLCAyNDUzIGdlbmVzIGFyZSB1cHJlZ3VsYXRlZCBpbiBDcm9obidzIGFuZCA1NzAyIGFyZSBkb3ducmVndWxhdGVkLg0KDQpgYGB7cn0NCiMgRXh0cmFjdCByZXN1bHRzIGFuZCBzaHJpbmsgbG9nMiBmb2xkIGNoYW5nZS4gc2F2ZSBhcyBzNCBnbG9iYWwgdmFyaWFibGUNCmdlbmVfcmVzIDwtIHJlc3VsdHMoZGRzX2dlbmUsIGNvbnRyYXN0ID0gYygiY29uZGl0aW9uIiwiY3JvaG5zIiwgImNvbnRyb2wiKSwgYWxwaGEgPSAwLjA1LCBsZmNUaHJlc2hvbGQgPSAwLjMyKQ0KZ2VuZV9yZXMgPC0gbGZjU2hyaW5rKGRkc19nZW5lLCBjb2VmID0gMiwgdHlwZSA9ICJhcGVnbG0iKQ0KIyBjcmVhdGUgbGlzdCB2YXJpYWJsZSBhbmQgc2F2ZSBhcyBkYXRhLmZyYW1lLCBnbG9iYWwgdmFyaWFibGUNCmdlbmVfcmVzX2FsbCA8LSBkYXRhLmZyYW1lKGdlbmVfcmVzKQ0KIyBzdWJzZXQgZ2VuZSByZXN1bHRzIGJ5IGxvZzJGb2xkQ2hhbmdlIHRvIGdldCB0b3AgMTAgdXByZWd1bGF0ZWQgYW5kIGRvd25yZWd1bGF0ZWQNCnNpZ0dlbmVzIDwtIHN1YnNldChnZW5lX3Jlc19hbGwsIGxvZzJGb2xkQ2hhbmdlID4gNC4xMSB8IGxvZzJGb2xkQ2hhbmdlIDwgLTguNikNCiMgcHJpbnQoZGF0YS5mcmFtZShzaWdHZW5lcykpDQoNCmBgYA0KVGhlIG1vc3QgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmUgdGhhdCBpcyBkb3ducmVndWxhdGVkIGluIENyb2huJ3MgaXMgUlAxMS0ySzYuMiwgd2hpbGUgdGhlIG1vc3QgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmUgdGhhdCBpcyB1cHJlZ3VsYXRlZCBpcyBQUkFDMS4NCg0KUGxvdHRpbmcgdGhlIHJlc3VsdHMNCg0KRmlyc3QsIHdlIGhhdmUgdG8gdHJhbnNmb3JtIG5vcm1hbGl6ZWQgY291bnRzIGJlZm9yZSB3ZSBjYW4gcGxvdCB0aGUgaGVhdG1hcC4gDQoNCmBgYHtyfQ0KIyB0cmFuc2Zvcm0gbm9ybWFsaXplZCBjb3VudHMuIHJ1bm5pbmcgdnN0KCkgYXBwbGllcyBhIHZhcmlhbmNlIHN0YWJpbGl6aW5nIHRyYW5zZm9ybWF0aW9uIHRvIHRoZSBjb3VudCBkYXRhDQp2c2QgPC0gdnN0KGRkc19nZW5lLCBibGluZCA9IEZBTFNFKQ0KDQojIG1hdGNoIHNpZ25pZmljYW50IGdlbmUgbmFtZXMgdG8gdGhlIHRyYW5zZm9ybWVkIGRhdGEgdnNkIHRvIHBsb3QgaGVhdG1hcA0Kcm93cyA8LSBtYXRjaChyb3cubmFtZXMoc2lnR2VuZXMpLCByb3cubmFtZXModnNkKSkNCm1hdCA8LSBhc3NheSh2c2QpW3Jvd3MsXQ0KbWF0IDwtIG1hdCAtIHJvd01lYW5zKG1hdCkNCg0KIyBwbG90IGhlYXRtYXANCmNvdWwgPC0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDgsICJQdUJ1R24iKSkoMjUpDQpwaGVhdG1hcChtYXQsIGNvbCA9IGNvdWwsIGZvbnRzaXplPTcsZm9udHNpemVfbnVtYmVyID0gMC40ICogZm9udHNpemUpDQpgYGANClRoZSBoZWF0bWFwIHNob3dzIHRoZSB0b3AgMTAgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGluIENyb2huJ3MgdnMgdGhlIGNvbnRyb2wgdGhhdCBhcmUgZG93bnJlZ3VsYXRlZCwgYW5kIHRoZSB0b3AgMTAgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIHRoYXQgYXJlIHVwcmVndWxhdGVkLiBUaGUgbG9nMiBGb2xkIENoYW5nZSBpcyBhIGxvZy1yYXRpbyBvZiB0aGUgZ2VuZSBleHByZXNzaW9uIHZhbHVlcyBpbiB0d28gY29uZGl0aW9uczogQ3JvaG4ncyBhbmQgY29udHJvbC4gQSBuZWdhdGl2ZSBsZmMgdmFsdWUgcmVwcmVzZW50cyBhIGdlbmUgdGhhdCBpcyBkb3ducmVndWxhdGVkIGluIENyb2huJ3MgdnMgdGhlIGNvbnRyb2wsIHdoaWxlIGEgcG9zaXRpdmUgbGZjIHZhbHVlIHJlcHJlc2VudHMgYSBnZW5lIHRoYXQgaXMgdXByZWd1bGF0ZWQgaW4gQ3JvaG4ncyB2cyB0aGUgY29udHJvbC4gVGhlIGxlZ2VuZCBvbiB0aGUgcmlnaHQgc2lnbmlmaWVzIGxvZzJmb2xkY2hhbmdlIHZhbHVlcyBieSBjb2xvciwgb24gYSBzY2FsZSBvZiAtMiB0byA2LiANCg0KDQpJIHdpbGwgcGxvdCB0aGUgcmVzdWx0cyBvZiBERVNlcSBhcyBhIHZvbGNhbm8gcGxvdCB3aGljaCBpcyB1c2VkIHRvIHZpc3VhbGl6ZSB0aGUgbG9nMihmb2xkY2hhbmdlKSB2YWx1ZXMgdnMgdGhlIC1sb2cocC12YWx1ZXMpLg0KDQpgYGB7cn0NCiMgUGxvdCByZXN1bHRzIG9mIERFU2VxIHRvIHZpc3VhbGl6ZSBkYXRhIGFzIGEgdm9sY2FubyBwbG90LiB0aGUgcGxvdCgpIGZ1bmN0aW9uIGlzIGJ1aWx0IGludG8gdGhlIGJhc2UgcGFja2FnZSBvZiBSLg0KcGxvdChyZXMkbG9nMkZvbGRDaGFuZ2UsICAtbG9nKHJlcyRwYWRqKSwgDQogICAgICB4bGFiPSJMb2cyKEZvbGRDaGFuZ2UpIiwNCiAgICAgIHlsYWI9Ii1Mb2coUC12YWx1ZSkiKQ0KYWJsaW5lKHY9YygtMiwyKSwgY29sPSJkYXJrZ3JheSIsIGx0eT0yKQ0KDQojcGxvdCBkaXNwZXJzaW9uIGVzdGltYXRlcw0KcGxvdERpc3BFc3RzKGRkc19nZW5lKQ0KYGBgDQpUaGUgdm9sY2FubyBwbG90IHNob3dzIHRoZSBnZW5lcmFsIHRyZW5kIG9mIHRoZSBkYXRhLCB3aXRoIGEgZ3JvdXAgb2YgZ2VuZXMgYXJvdW5kIHRoZSAtMjUgbGZjIHZhbHVlIHdoaWxlIHRoZSByZXN0IGFyZSBncm91cGVkIGJldHdlZW4gLTEwIGFuZCA1LiBUaGUgZGlzcGVyc2lvbiBwbG90IHNob3dzIHRoZSB2YXJpYW5jZSBpbiBnZW5lIGV4cHJlc3Npb24gZm9yIHRoZSBERVNlcSBkYXRhLCB3aXRoIHRoZSByZWQgbGluZSBzaWduaWZ5aW5nIHRoZSBmaXR0ZWQgbGluZSBmb3IgdGhlIGRhdGEgc2hvd24uIEJhc2VkIG9uIHRoZSBncmFwaHMsIHRoZXJlIGRvIG5vdCBhcHBlYXIgdG8gYmUgYW55IG91dGxpZXJzIGFuZCB0aGUgZGF0YSBhcHBlYXJzIGNvbnNpc3RlbnQuDQoNCkkgaGF2ZSBkb3dubG9hZGVkIGEgRkFTVEEgZmlsZSBmcm9tIE5DQkkgZm9yIHRoZSBnZW5lIFBSQUMxLCB3aGljaCBpcyB0aGUgbW9zdCBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYW5kIHVwcmVndWxhdGVkIGdlbmUgaW4gQ3JvaG4ncy4gSSB3aWxsIHJ1biBCTEFTVCBvbiB0aGlzIHNlcXVlbmNlIHRvIGRldGVybWluZSB0aGUgdG9wIDEwIGhpdHMuDQoNCmBgYHtyfQ0KIyBsaXN0IHZhcmlhYmxlLCBnbG9iYWwNCkROQV9mYXN0YSA8LSByZWFkLmZhc3RhKCJQUkFDMS5mYXN0YSIpDQojIHM0IHZhcmlhYmxlLCBnbG9iYWwNCkROQV9QUkFDMSA8LSByZWFkRE5BU3RyaW5nU2V0KCJQUkFDMS5mYXN0YSIsIGZvcm1hdD0iZmFzdGEiKQ0KIyBydW4gQkxBU1Qgb24gczQgdmFyaWFibGUNCmJsYXN0U2VxdWVuY2VzKEROQV9QUkFDMSwgIm5yIiwgaGl0TGlzdFNpemU9IjEwIiwgZmlsdGVyPSJMIiwgZXhwZWN0PSIxMCIsIHByb2dyYW09ImJsYXN0biIsIGFzPWMoImRhdGEuZnJhbWUiKSkNCmBgYA0KVGhlIG1vc3QgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmUgZm91bmQgaW4gdGhlIGRhdGEgc2V0IGNvbnRhaW5pbmcgQ3JvaG4ncyBzYW1wbGVzIG9mIGhvbW8gc2FwaWVucyBpcyBQUkFDMSwgd2hpY2ggaXMgYSBzbWFsbCBudWNsZWFyIHByb3RlaW4uIFRoZSBQUkFDMSBnZW5lIGhhcyBiZWVuIGZvdW5kIHRvIGJlIG1vcmUgZXhwcmVzc2VkIGluIHRpc3N1ZXMgc3VjaCBhcyB0aGUgcHJvc3RhdGUgYW5kIGNvbG9uLCBhbmQgaGFzIGJlZW4gbGlua2VkIHRvIHByb3N0YXRlIGNhbmNlciAoS2ltIGV0IGFsLiwgMjAxNSkuIFRoaXMgZ2VuZSBpcyBmb3VuZCBpbiBjbG9zZSBwaHlsb2dlbmV0aWMgcmVsYXRpdmVzIG9mIGhvbW8gc2FwaWVucywgYnV0IGEgbGFjayBvZiBldmlkZW5jZSBleGlzdHMgdG8gc2hvdyBpZiB0aGVzZSBzcGVjaWVzIGV4cHJlc3MgdGhlIFBSQUMxIGdlbmUuIA0KDQpUaGUgQkxBU1Qgc2VhcmNoIHJ1bnMgdGhlIFBSQUMxIG51Y2xlb3RpZGUgc2VxdWVuY2UgdGhyb3VnaCBOQ0JJIEJMQVNULCBhbmQgcmV0dXJucyB0aGUgdG9wIDEwIG1hdGNoZXMgaGVyZS4gVGhlcmUgYXJlIDUgbWF0Y2hlcyB0byBjbG9zZSBwaHlsb2dlbmV0aWMgcmVsYXRpdmVzIG9mIGhvbW8gc2FwaWVuczogQm9ub2JvIChQYW4gcGFuaXNjdXMpLCBDaGltcGFuemVlIChQYW4gdHJvZ2xvZHl0ZXMpLCBHb3JpbGxhIChHb3JpbGxhIGdvcmlsbGEpLCBPcmFuZ3V0YW4gKFBvbmdvIGFiZWxpaSksIGFuZCBHaWJib24gKE5vbWFzY3VzIGxldWNvZ2VueXMpLiBFYWNoIG9mIHRoZXNlIGFwcGVhcnMgYXMgInByZWRpY3RlZCwiIHdoaWNoIG1lYW5zIHRoYXQgYWx0aG91Z2ggdGhlIG51Y2xlb3RpZGUgc2VxdWVuY2Ugb2YgdGhlIFBSQUMxIGdlbmUgaXMgc2ltaWxhciB0byB0aGVzZSBzcGVjaWVzLCB0aGVyZSBpcyBubyBleHBlcmltZW50YWwgZXZpZGVuY2Ugc2hvd2luZyB0aGF0IHRoaXMgZ2VuZSBpcyB0cmFuc2NyaWJlZCB0byBwcm9kdWNlIGEgcHJvdGVpbi4gVGhlIHNlcXVlbmNlIG1hdGNoIGlzIGFzIGhpZ2ggYXMgOTguODUlIGZvciB0aGUgQm9ub2JvIGFuZCBhcyBsb3cgYXMgODYuMTAlIGZvciB0aGUgR2liYm9uLCBob3dldmVyIHRoZXJlIGlzIG5vIGV2aWRlbmNlIHNob3dpbmcgdGhhdCB0aGUgZ2Vub21lcycgb2YgdGhlc2UgZml2ZSBzcGVjaWVzIGV4cHJlc3MgdGhpcyBnZW5lLg==